package storage.metadata;

import java.util.*;

import engine.query.Plan;
import engine.query.TablePlan;
import engine.query.UpdateScan;

import storage.record.*;
import storage.tx.Transaction;
import static storage.record.Schema.*;

public class TableMgr {

	public static final int MAX_NAME = 16;

	private TableInfo tcatinfo, fcatinfo;

	public TableMgr(boolean isNew, Transaction tx) {
		Schema tcatSchema = new Schema();
		tcatSchema.addStringField("tblname", MAX_NAME);
		tcatSchema.addIntField("reclength");
		tcatinfo = new TableInfo("tblcat", tcatSchema);

		Schema fcatSchema = new Schema();
		fcatSchema.addStringField("tblname", MAX_NAME);
		fcatSchema.addStringField("fldname", MAX_NAME);
		fcatSchema.addIntField("type");
		fcatSchema.addIntField("length");
		fcatSchema.addIntField("offset");
		fcatSchema.addIntField("iskey");
		fcatSchema.addIntField("notnull");
		fcatSchema.addIntField("fkey");
		fcatSchema.addIntField("ischeck");
		fcatSchema.addIntField("isreferenced");
		fcatSchema.addStringField("rktblname", MAX_NAME);
		fcatSchema.addStringField("rkfldname", MAX_NAME);
		fcatSchema.addStringField("fkeytblname", MAX_NAME);
		fcatSchema.addStringField("fkeyfldname", MAX_NAME);
		fcatSchema.addStringField("termstring", MAX_NAME);
		fcatinfo = new TableInfo("fldcat", fcatSchema);

		if (isNew) {
			createTable("tblcat", tcatSchema, tx);
			createTable("fldcat", fcatSchema, tx);
		}
	}

	public List<String> getTablenames(Transaction tx){
		List<String> result = new ArrayList<String>();
		RecordFile tcatfile = new RecordFile(tcatinfo, tx);
		while(tcatfile.next()){
			String tblname = tcatfile.getString("tblname");
			if(!tblname.equals("tblcat")&&!tblname.equals("fldcat")&&!tblname.equals("viewcat")&&!tblname.equals("idxcat"))
				result.add(tblname);
		}
		tcatfile.close();
		return result;
	}
	
	public void refreshSchema(String tblname, String fldname, String rtblname,
			String rfldname, Transaction tx) {
		RecordFile fcatfile = new RecordFile(fcatinfo, tx);
		while (fcatfile.next())
			if (fcatfile.getString("tblname").equals(tblname)
					&& fcatfile.getString("fldname").equals(fldname)) {

				System.err.println("before set:");
				int is = fcatfile.getInt("isreferenced");
				System.out.println("is:" + is);
				String tb = fcatfile.getString("rktblname");
				System.out.println("rktblname:" + tb);
				String fd = fcatfile.getString("rkfldname");
				System.out.println("rkfldname:" + fd);

				fcatfile.setInt("isreferenced", TRUE);
				fcatfile.setString("rktblname", rtblname);
				fcatfile.setString("rkfldname", rfldname);

				System.err.println("after set:");
				int is2 = fcatfile.getInt("isreferenced");
				System.out.println("is:" + is2);
				String tb2 = fcatfile.getString("rktblname");
				System.out.println("rktblname:" + tb2);
				String fd2 = fcatfile.getString("rkfldname");
				System.out.println("rkfldname:" + fd2);

				// System.out.println("refreshSchema:"+tblname + " " + fldname +
				// "||" +rtblname+" "+rfldname);
			}
		fcatfile.close();
	}

	public void createTable(String tblname, Schema schema, Transaction tx) {
		TableInfo ti = new TableInfo(tblname, schema);

		RecordFile tcatfile = new RecordFile(tcatinfo, tx);
		tcatfile.insert();
		tcatfile.setString("tblname", tblname);
		tcatfile.setInt("reclength", ti.recordLength());
		tcatfile.close();

		RecordFile fcatfile = new RecordFile(fcatinfo, tx);
		for (String fldname : schema.fields()) {
			fcatfile.insert();
			fcatfile.setString("tblname", tblname);
			fcatfile.setString("fldname", fldname);
			fcatfile.setInt("type", schema.type(fldname));
			fcatfile.setInt("length", schema.length(fldname));
			fcatfile.setInt("offset", ti.offset(fldname));
			fcatfile.setInt("iskey", schema.iskey(fldname));
			fcatfile.setInt("notnull", schema.notnull(fldname));
			int fkey = schema.fkey(fldname);
			fcatfile.setInt("fkey", fkey);
			if (fkey == TRUE) {
				fcatfile.setString("fkeytblname", schema.fkeytblname(fldname));
				fcatfile.setString("fkeyfldname", schema.fkeyfldname(fldname));
			}
			int ischeck = schema.ischeck(fldname);
			fcatfile.setInt("ischeck", ischeck);
			if (ischeck == TRUE) {
				fcatfile.setString("termstring", schema.termstring(fldname));
			}
			int isreferenced = schema.isreferenced(fldname);
			fcatfile.setInt("isreferenced", isreferenced);
			if (isreferenced == TRUE) {
				fcatfile.setString("rktblname", schema.rktblname(fldname));
				fcatfile.setString("rkfldname", schema.rkfldname(fldname));
			}
		}
		fcatfile.close();
	}

	public TableInfo getTableInfo(String tblname, Transaction tx) {
		RecordFile tcatfile = new RecordFile(tcatinfo, tx);
		int reclen = -1;
		while (tcatfile.next()) {
			if (tcatfile.getString("tblname").equals(tblname)) {
				reclen = tcatfile.getInt("reclength");
				break;
			}
		}
		tcatfile.close();

		RecordFile fcatfile = new RecordFile(fcatinfo, tx);
		Schema sch = new Schema();
		Map<String, Integer> offsets = new HashMap<String, Integer>();
		while (fcatfile.next()) {
			if (fcatfile.getString("tblname").equals(tblname)) {
				String fldname = fcatfile.getString("fldname");
				int fldtype = fcatfile.getInt("type");
				int fldlen = fcatfile.getInt("length");
				int offset = fcatfile.getInt("offset");
				int iskey = fcatfile.getInt("iskey");
				int notnull = fcatfile.getInt("notnull");
				int fkey = fcatfile.getInt("fkey");
				int ischeck = fcatfile.getInt("ischeck");
				int isreferenced = fcatfile.getInt("isreferenced");
				String fkeytblname, fkeyfldname, termstring, rktblname, rkfldname;
				if (fkey == TRUE) {
					fkeytblname = fcatfile.getString("fkeytblname");
					fkeyfldname = fcatfile.getString("fkeyfldname");
				} else {
					fkeytblname = null;
					fkeyfldname = null;
				}
				if (ischeck == TRUE) {
					termstring = fcatfile.getString("termstring");
				} else
					termstring = null;
				if (isreferenced == TRUE) {
					rktblname = fcatfile.getString("rktblname");
					rkfldname = fcatfile.getString("rkfldname");
				} else {
					rktblname = null;
					rkfldname = null;
				}
				offsets.put(fldname, offset);
				sch.addField(fldname, fldtype, fldlen, iskey, notnull, fkey,
						ischeck, fkeytblname, fkeyfldname, termstring,
						isreferenced, rktblname, rkfldname);
			}
		}
		fcatfile.close();
		return new TableInfo(tblname, sch, offsets, reclen);
	}
}
